package org.hit.burkun.obo.dbimport;

import java.util.Map;

import org.hit.burkun.db.DBTypeConverter;
import org.hit.burkun.db.DBTypeConverter.DATATYPE;
import org.hit.burkun.obo.model.Dbxref;
import org.hit.burkun.obo.model.Relationship;
import org.hit.burkun.obo.model.Subset;
import org.hit.burkun.obo.model.Synonym;
import org.hit.burkun.obo.model.Term;

public class OboTable {
	private String termTb = "term";
	private String term2termTb = "term2term";
	private String term2SynTb = "term_synonym";
	private String term2refTb = "term_dbxref";
	private String term2propertyTb = "term_property";
	private String term2subsetTb = "term_subset";

	private ONTOLOGYNAME preffix = ONTOLOGYNAME.GO;

	private DBTypeConverter termC;
	private DBTypeConverter term2termC;
	private DBTypeConverter term2SynC;
	private DBTypeConverter term2refC;
	private DBTypeConverter term2propertyC;
	private DBTypeConverter term2subsetC;

	public enum ONTOLOGYNAME {
		GO("go_"), DO("do_"), HPO("hp_"), CHEBI("chebi_"), MP("mp_");
		private String tag;

		ONTOLOGYNAME(String tag) {
			this.tag = tag;
		}

		public String getTag() {
			return tag;
		}

		@Override
		public String toString() {
			return tag;
		}

		public String toOntogyType() {
			if (this == GO) {
				return "GO";
			} else if (this == HPO) {
				return "HPO";
			} else if (this == DO) {
				return "DO";
			} else if (this == CHEBI) {
				return "CHEBI";
			}
			return "";
		}
	}

	public OboTable() {
		initDBCov();
	}

	public OboTable(ONTOLOGYNAME preffix) {
		this.preffix = preffix;
		initDBCov();
	}

	private void initDBCov() {
		DATATYPE[] termTbc = new DATATYPE[9];
		termTbc[0] = DATATYPE.I;
		termTbc[6] = DATATYPE.I;
		termTbc[7] = DATATYPE.I;
		termTbc[8] = DATATYPE.I;
		termC = new DBTypeConverter(termTbc);

		DATATYPE[] term2termTbc = new DATATYPE[4];
		term2termTbc[0] = DATATYPE.I;
		term2termTbc[1] = DATATYPE.I;
		term2termTbc[3] = DATATYPE.I;
		term2termC = new DBTypeConverter(term2termTbc);

		DATATYPE[] term2SynTbc = new DATATYPE[5];
		term2SynTbc[0] = DATATYPE.I;
		term2SynC = new DBTypeConverter(term2SynTbc);

		DATATYPE[] term2refTbc = new DATATYPE[6];
		term2refTbc[0] = DATATYPE.I;
		term2refTbc[3] = DATATYPE.I;
		term2refC = new DBTypeConverter(term2refTbc);

		DATATYPE[] term2propertyTbc = new DATATYPE[3];
		term2propertyTbc[0] = DATATYPE.I;
		term2propertyC = new DBTypeConverter(term2propertyTbc);

		DATATYPE[] term2subsetTbc = new DATATYPE[2];
		term2subsetTbc[0] = DATATYPE.I;
		term2subsetC = new DBTypeConverter(term2subsetTbc);

	}

	public DBTypeConverter getTermC() {
		return termC;
	}

	public void setTermC(DBTypeConverter termC) {
		this.termC = termC;
	}

	public DBTypeConverter getTerm2termC() {
		return term2termC;
	}

	public void setTerm2termC(DBTypeConverter term2termC) {
		this.term2termC = term2termC;
	}

	public DBTypeConverter getTerm2SynC() {
		return term2SynC;
	}

	public void setTerm2SynC(DBTypeConverter term2SynC) {
		this.term2SynC = term2SynC;
	}

	public DBTypeConverter getTerm2refC() {
		return term2refC;
	}

	public void setTerm2refC(DBTypeConverter term2refC) {
		this.term2refC = term2refC;
	}

	public DBTypeConverter getTerm2propertyC() {
		return term2propertyC;
	}

	public void setTerm2propertyC(DBTypeConverter term2propertyC) {
		this.term2propertyC = term2propertyC;
	}

	public DBTypeConverter getTerm2subsetC() {
		return term2subsetC;
	}

	public void setTerm2subsetC(DBTypeConverter term2subsetC) {
		this.term2subsetC = term2subsetC;
	}

	public ONTOLOGYNAME getPreffix() {
		return preffix;
	}

	public void setPreffix(ONTOLOGYNAME preffix) {
		this.preffix = preffix;
	}

	public String getTermTbName() {
		return preffix.toString() + termTb;
	}

	public String getTerm2termTbName() {
		return preffix.toString() + term2termTb;
	}

	public String getTerm2SynTbName() {
		return preffix.toString() + term2SynTb;
	}

	public String getTerm2refTbName() {
		return preffix.toString() + term2refTb;
	}

	public String getTerm2propertyTbName() {
		return preffix.toString() + term2propertyTb;
	}

	public String getTerm2subsetTbName() {
		return preffix.toString() + term2subsetTb;
	}

	public String[] makeDbTermLine(int counter, Term term) {
		int proNum = termC.getTypes().length;
		String[] res = new String[proNum];
		res[0] = String.valueOf(counter);
		res[1] = term.getName();
		res[2] = term.getNamesapce();
		res[3] = term.getId();
		res[4] = term.getDef();
		res[5] = term.getComment();
		res[6] = term.isIs_obsolete() ? "1" : "0";
		res[7] = "0";
		res[8] = "0";
		return res;
	}

	public String[] makeDbTerm2TermLine(Map<String, String> mapper,
			String sourceTerm, Relationship rel) {
		int proNum = term2termC.getTypes().length;
		String[] res = new String[proNum];
		String termId = rel.getTermID();
		if (mapper.containsKey(sourceTerm)) {
			res[0] = mapper.get(sourceTerm);
			if (mapper.containsKey(termId)) {
				res[1] = mapper.get(termId);
				res[2] = rel.getRelationStr();
				res[3] = "0";
				return res;
			}
			return null;
		} else {
			return null;
		}
	}

	public String[] makeDbTerm2SynLine(Map<String, String> mapper,
			String sourceTerm, Synonym syn) {
		int proNum = term2SynC.getTypes().length;
		String[] res = new String[proNum];
		if (mapper.containsKey(sourceTerm)) {
			res[0] = mapper.get(sourceTerm);
			res[1] = syn.getName();
			res[2] = syn.getAccSynonym();
			res[3] = syn.getType().getTag();
			res[4] = syn.getCategory();
			return res;
		} else {
			return null;
		}
	}

	public String[] makeDbTerm2RefLine(Map<String, String> mapper,
			String sourceTerm, Dbxref ref) {
		int proNum = term2refC.getTypes().length;
		String[] res = new String[proNum];
		if (mapper.containsKey(sourceTerm)) {
			res[0] = mapper.get(sourceTerm);
			res[1] = ref.getIdref().key;
			res[2] = ref.getIdref().value;
			res[3] = ref.isFromDefinition() ? "1" : "0";
			res[4] = "";
			res[5] = ref.getXrefDesc();
			return res;
		} else {
			return null;
		}
	}

	public String[] makeDbTerm2SubsetLine(Map<String, String> mapper,
			String sourceTerm, Subset subset) {
		int proNum = term2subsetC.getTypes().length;
		String[] res = new String[proNum];
		if (mapper.containsKey(sourceTerm)) {
			res[0] = mapper.get(sourceTerm);
			res[1] = subset.getName();
			return res;
		} else {
			return null;
		}
	}

	// property name
	public String[] makeDbTerm2PropertyLine(Map<String, String> mapper,
			String sourceTerm, Subset subset) {
		int proNum = term2subsetC.getTypes().length;
		String[] res = new String[proNum];
		if (mapper.containsKey(sourceTerm)) {
			res[0] = mapper.get(sourceTerm);
			res[1] = subset.getName();
			return res;
		} else {
			return null;
		}
	}

	// add by calculate geneid
	private String term2geneIDs = "geneid";

	public String getGeneIDTbName() {
		return preffix + term2geneIDs;
	}
}
